package calculatePlus;

import java.util.LinkedList;

public class Expression extends LinkedList<NumSign> {
    @Override
    public String toString() {
        String str = "";
        for (NumSign numSign : this) {
            str += numSign.getStrNum() + numSign.getSign();
        }

        return str;
    }

    public double calculate() {
        this.calSingleOpt();
        this.calMulAndDiv();
        this.calAddAndSub();
        return this.get(0).getNum();
    }

    private void calSingleOpt() {
        for (int i = 0; i < this.size(); i++) {
            if (this.size() == 1)   return;
            String opt = this.get(i).getSign();
            double temp = this.get(i).getNum();

            switch (opt) {
                case "x^2":
                    temp = temp * this.get(i).getNum();
                    this.get(i + 1).setNum(temp);
                    this.remove(i);
                    i = -1;
                    break;
                case "1/x":
                    temp = 1 / temp;
                    this.get(i + 1).setNum(temp);
                    this.remove(i);
                    i = -1;
                    break;
                case "sin":
                    temp = Math.sin(temp);
                    this.get(i + 1).setNum(temp);
                    this.remove(i);
                    i = -1;
                    break;
                case "cos":
                    temp = Math.cos(temp);
                    this.get(i + 1).setNum(temp);
                    this.remove(i);
                    i = -1;
                    break;
                case "tan":
                    temp = Math.tan(temp);
                    this.get(i + 1).setNum(temp);
                    this.remove(i);
                    i = -1;
                    break;
                case "√":
                    temp = Math.sqrt(temp);
                    this.get(i + 1).setNum(temp);
                    this.remove(i);
                    i = -1;
                    break;
                case "10^x":
                    temp = Math.pow(10, temp);
                    this.get(i + 1).setNum(temp);
                    this.remove(i);
                    i = -1;
                    break;
                case "log":
                    temp = Math.log10(temp);
                    this.get(i + 1).setNum(temp);
                    this.remove(i);
                    i = -1;
                    break;
                case "exp":
                    temp = Math.exp(temp);
                    this.get(i + 1).setNum(temp);
                    this.remove(i);
                    i = -1;
                    break;
            }
        }
    }

    private void calMulAndDiv() {
        for (int i = 0; i < this.size(); i++) {
            if (this.size() == 1)   return;
            if (this.get(i).getSign().equals("*")) {
                double temp = this.get(i).getNum() * this.get(i + 1).getNum();
                this.get(i + 1).setNum(temp);
                this.remove(i);
                i = -1;
                continue;
            }
            if (this.get(i).getSign().equals("/")) {
                double temp = this.get(i).getNum() / this.get(i + 1).getNum();
                this.get(i + 1).setNum(temp);
                this.remove(i);
                i = -1;
                continue;
            }
            if (this.get(i).getSign().equals("%") || this.get(i).getSign().equals("mod")) {
                double temp = this.get(i).getNum() % this.get(i + 1).getNum();
                this.get(i + 1).setNum(temp);
                this.remove(i);
                i = -1;
                continue;
            }
        }
    }

    private void calAddAndSub() {
        for (int i = 0; i < this.size(); i++) {
            if (this.size() == 1) return;
            if (this.get(i).getSign().equals("+")) {
                double temp = this.get(i).getNum() + this.get(i + 1).getNum();
                this.get(i + 1).setNum(temp);
                this.remove(i);
                i = -1;
                continue;
            }
            if (this.get(i).getSign().equals("-")) {
                double temp = this.get(i).getNum() - this.get(i + 1).getNum();
                this.get(i + 1).setNum(temp);
                this.remove(i);
                i = -1;
                continue;
            }
        }
    }
}
